﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using DaVikingCode.AssetPacker;
using DaVikingCode.RectanglePacking;
using UnityEditor;
using UnityEngine;

public class AtlasPacker
{
    public static float pixelsPerUnit = 100.0f;
    const int padding = 2;
    static List<TextureToPack> itemsToRaster = new List<TextureToPack>();

    public static void MakeAtlas(string srcPath, string desPath, string atlasName)
    {
        if (!Directory.Exists(srcPath))
        {
            Debug.LogError("path not find!>>" + srcPath);
            return;
        }

        string[] files = Directory.GetFiles(srcPath, "*.png");
        if (files.Length > 0)
        {
            foreach (var file in files)
            {
                itemsToRaster.Add(new TextureToPack(file, Path.GetFileNameWithoutExtension(file)));
            }
        }
        CreateAtlas(desPath, atlasName);
    }

    static void CreateAtlas(string desPath, string atlasName)
    {
        //创建目录
        FileHelper.CreateDirectory(desPath);

        //读取图片
        List<string> images = new List<string>();
        List<Texture2D> textures = new List<Texture2D>();
        List<Rect> rectangles = new List<Rect>();
        foreach (TextureToPack itemToRaster in itemsToRaster)
        {
            var texture = AssetDatabase.LoadAssetAtPath<Texture2D>(itemToRaster.file);
            images.Add(itemToRaster.id);
            textures.Add(texture);
        }
        itemsToRaster.Clear();

        //计算总面积
        float maxWidth = 0;
        float maxHeight = 0;
        float area = 0;
        for (int i = 0; i < textures.Count; i++)
        {
            Texture2D tex = textures[i];
            maxWidth = Math.Max(maxWidth, tex.width);
            maxHeight = Math.Max(maxHeight, tex.height);
            area += (tex.width + padding) * (tex.height + padding);
            rectangles.Add(new Rect(0, 0, tex.width, tex.height));
        }

        //计算图集尺寸
        int textureSize = 2;
        while (textureSize < maxWidth) textureSize *= 2;
        while (textureSize < maxHeight) textureSize *= 2;
        while (textureSize * textureSize < area) textureSize *= 2;

        while (rectangles.Count > 0)
        {
            //执行打图集逻辑，生成图集数据
            RectanglePacker packer = new RectanglePacker(textureSize, textureSize, padding);
            for (int i = 0; i < rectangles.Count; i++)
                packer.insertRectangle((int)rectangles[i].width, (int)rectangles[i].height, i);
            packer.packRectangles();

            //生成空白图集
            Texture2D texture = new Texture2D(textureSize, textureSize, TextureFormat.ARGB32, false);
            Color32[] fillColor = texture.GetPixels32();
            for (int i = 0; i < fillColor.Length; ++i)
                fillColor[i] = Color.clear;

            //将图集数据写入空白图集
            if (packer.rectangleCount > 0)
            {
                texture.SetPixels32(fillColor);
                IntegerRectangle rect = new IntegerRectangle();
                List<TextureAsset> textureAssets = new List<TextureAsset>();
                List<Rect> garbageRect = new List<Rect>();
                List<Texture2D> garabeTextures = new List<Texture2D>();
                List<string> garbageImages = new List<string>();

                for (int j = 0; j < packer.rectangleCount; j++)
                {
                    int index = packer.getRectangleId(j);
                    rect = packer.getRectangle(j, rect);
                    texture.SetPixels32(rect.x, rect.y, rect.width, rect.height, textures[index].GetPixels32());
                    TextureAsset textureAsset = new TextureAsset();
                    textureAsset.x = rect.x;
                    textureAsset.y = rect.y;
                    textureAsset.width = rect.width;
                    textureAsset.height = rect.height;
                    textureAsset.name = images[index];

                    textureAssets.Add(textureAsset);

                    garbageRect.Add(rectangles[index]);
                    garabeTextures.Add(textures[index]);
                    garbageImages.Add(images[index]);
                }

                foreach (Rect garbage in garbageRect)
                    rectangles.Remove(garbage);

                foreach (Texture2D garbage in garabeTextures)
                    textures.Remove(garbage);

                foreach (string garbage in garbageImages)
                    images.Remove(garbage);

                texture.Apply();

                File.WriteAllBytes(string.Format("{0}/{1}.png", desPath, atlasName), texture.EncodeToPNG());
                File.WriteAllText(string.Format("{0}/{1}.json", desPath, atlasName), JsonUtility.ToJson(new TextureAssets(textureSize, textureSize, textureAssets.ToArray())));
            }
        }
    }
}
